namespace cpputils
{

template<class TYPE>
struct array
{
public:
	typedef TYPE value_type;

	array() : Ptr(0), Size(0) {}
	explicit array(int SetSize) : Ptr(0), Size(0)
	{
		resize(SetSize);
	}
	array(int SetSize, const TYPE& SetValue) : Ptr(0), Size(0)
	{
		assign(SetSize, SetValue);
	}
	array(const TYPE* Begin, const TYPE* End) : Ptr(0), Size(0)
	{
		assign(Begin, End);
	}
	array(const array& SetArray) : Ptr(0), Size(0)
	{
		*this = SetArray;
	}
	~array()
	{
		delete[] Ptr;
	}
	void clear()
	{
		delete[] Ptr;
		Ptr = 0;
		Size = 0;
	}
	void resize(int SetSize)
	{
		if (SetSize != Size)
		{
			TYPE* NewPtr = SetSize == 0 ? 0 : new TYPE[SetSize];
			delete[] Ptr;
			Ptr = NewPtr;
			Size = SetSize;
		}
	}
	void assign(int SetSize, const TYPE& SetValue)
	{
		resize(SetSize);
		fill(Ptr, Ptr + SetSize, SetValue);
	}
	void assign(const TYPE* Begin, const TYPE* End)
	{
		resize(End - Begin);
		copy(Begin, End, Ptr);
	}
	array& operator=(const array& SetArray)
	{
		if (this == &SetArray) return *this;
		resize(SetArray.Size);
		copy(SetArray.begin(), SetArray.end(), Ptr);
		return *this;
	}
	void swap(array& Other)
	{
		std::swap(Ptr, Other.Ptr);
		std::swap(Size, Other.Size);
	}
	const TYPE& operator[](int I) const
	{
		return Ptr[I];
	}
	TYPE& operator[](int I)
	{
		return Ptr[I];
	}
	bool empty() const
	{
		return Ptr == 0;
	}
	int size() const
	{
		return Size;
	}
	const TYPE& front() const
	{
		return *Ptr;
	}
	TYPE& front()
	{
		return *Ptr;
	}
	const TYPE& back() const
	{
		return Ptr[Size - 1];
	}
	TYPE& back()
	{
		return Ptr[Size - 1];
	}
	const TYPE* begin() const
	{
		return Ptr;
	}
	TYPE* begin()
	{
		return Ptr;
	}
	const TYPE* end() const
	{
		return Ptr + Size;
	}
	TYPE* end()
	{
		return Ptr + Size;
	}
private:
	TYPE* Ptr;
	int Size;
};

using std::swap;

template<class TYPE>
inline void swap(cpputils::array<TYPE>& A, cpputils::array<TYPE>& B)
{
	A.swap(B);
}

}
